#include"threadpool.hpp"
#include<string.h>

ThreadPool::ThreadPool(int numWorks,int _max_jobs=10)
    :sum_thread(numWorks),free_thread(numWorks),max_jobs(_max_jobs)
{
    if(sum_thread<1||max_jobs<1)std::cout<<"thread run error"<<std::endl;
    if(pthread_cond_init(&cond_jobs,nullptr)!=0)
    {
        std::cout<<"pthread_cond_init error"<<std::endl;
    }
    if(pthread_mutex_init(&mutex,nullptr)!=0)
    {
        std::cout<<"pthread_mutex_init error"<<std::endl;
    }
    struct WORKS* thread_list=new struct WORKS[sum_thread];
    if(thread_list==nullptr)std::cout<<"new error"<<std::endl;
    for(int i=0;i<sum_thread;i++)
    {
        thread_list[i].pool=this;//访问线程池资源成员
        int ret=pthread_create(&thread_list[i].pthid,nullptr,_run,&thread_list[i]);
        if(ret)
        {
            delete[] thread_list;
            std::cout<<"create thread error"<<std::endl;
        }
        ret=pthread_detach(thread_list[i].pthid);
        if(ret)
        {
            delete[] thread_list;
            std::cout<<"detach thread error"<<std::endl;
        }
        thread_list[i].terminate=false;
    }
}




ThreadPool:: ~ThreadPool()
{
    for(int i=0;i<sum_thread;i++)
        thread_list[i].terminate=true;
    pthread_mutex_lock(&mutex);
    pthread_cond_broadcast(&cond_jobs);
    pthread_mutex_unlock(&mutex);
    delete[] thread_list;
}




void ThreadPool::PushJob(void(*f)(void*arg),void* arg,int len)
{
    struct JOBS* job=(struct JOBS*)malloc(sizeof(struct JOBS));
    if(job==nullptr)
    {
        std::cout<<"malloc失败"<<std::endl;
        return;
    }
    memset(job,0,sizeof(struct JOBS));
    job->user_data=malloc(len);
    if(job->user_data==nullptr)
    {
        std::cout<<"malloc失败"<<std::endl;
        return;
    }
    memcpy(job->user_data,arg,len);
    job->func=f;
    _addJob(job);
}



void ThreadPool::_addJob(JOBS* job)
{
    pthread_mutex_lock(&mutex);
    while(jobs_list.size()>=max_jobs)
    {
        pthread_cond_signal(&cond_jobs);
    }
    jobs_list.push_back(job);
    pthread_cond_signal(&cond_jobs);
    pthread_mutex_unlock(&mutex);
}



void* ThreadPool::_run(void* arg)
{
    struct WORKS* work=(struct WORKS*)arg;
    work->pool->threadLoop(arg);
}



void ThreadPool::threadLoop(void* arg)
{
    struct WORKS* work=(struct WORKS*)arg;
    while(1)
    {
        pthread_mutex_lock(&mutex);
        while(jobs_list.size()==0)
        {
            if(work->terminate)
            {
                break;
            }
            pthread_cond_wait(&cond_jobs,&mutex);
        }
        if(work->terminate)
        {
            pthread_mutex_unlock(&mutex);
            break;
        }
        struct JOBS* job=jobs_list.front();
        jobs_list.pop_front();
        pthread_cond_signal(&cond_jobs);
        pthread_mutex_unlock(&mutex);
        free_thread--;
        work->isrunning=true;
        job->func(job->user_data);//调用函数Print
        work->isrunning=false;
        free(job->user_data);
        free(job);
    }
    free(work);
    pthread_exit(NULL);
}